<template>
  <div>
    <div class="dashboard-container">首页</div>
    <!-- 新组件库使用的注意事项
    1.熟悉组件库中有哪些现有的组件 对应常用组件 card,form(input,readio,checkbox,select,Cascader,button) table,pagitation,upload
    2.根据ui设计图找到对应的组件 将最合适的组件实例代码cv到项目中
    3.根据实际项目需求进行修改
    4.如果有新的属性和方法看一下组件库中当前组件的文档（属性attribute，methods，slot）
    5.根据实际需求定制自己的组件 -->
    <div class="app-container">
      <!-- 面板结构 -->
      <el-card v-loading="loading">
        <TreeTools :node-data="company" :is-root="true" @add="add" @del="del" @edit="edit" />
        <!-- 树形结构内容 -->
        <!-- el-tree 身上绑定 :data="树形结构数据" 就能渲染出树形结构 -->
        <el-tree :data="list" :props="defaultProps" default-expand-all>
          <!-- 作用域插槽的使用 -->
          <!-- node：el-tree 底层的节点信息 -->
          <!-- data：拿到的是每个节点的数据对象 -->
          <!-- 1.使用作用域插槽需要让外层标签成对出现
          2.在组件标签里面添加一个template标签
          3.再template标签上绑定#default={结构出来的数据}
          4.在其他的标签里面使用作用域插槽返回来的数据 -->
          <template #default="{ data }">
            <TreeTools :node-data="data" @add="add" @del="del" @edit="edit" />
          </template>
        </el-tree>
      </el-card>
    </div>
    <!-- dialog弹层显示 -->
    <el-dialog
      :title="title"
      :visible="dialogVisible"
      width="50%"
      @open="dialogOpen"
      @close="closeDialog"
    >
      <!-- 表单校验 -->
      <el-form ref="departRef" :model="departForm" :rules="departRules" label-width="120px">
        <el-form-item label="部门名称" prop="name">
          <el-input v-model="departForm.name" style="width:80%" placeholder="1-50个字符" />
        </el-form-item>
        <el-form-item label="部门编码" prop="code">
          <el-input v-model="departForm.code" style="width:80%" placeholder="1-50个字符" />
        </el-form-item>
        <el-form-item label="部门负责人" prop="manager">
          <el-select v-model="departForm.manager" style="width:80%" placeholder="请选择">
            <!-- label 展示给用户看的
            value 传递数据给后台的 -->
            <el-option
              v-for="item in employeeList"
              :key="item.id"
              :label="item.username"
              :value="item.username"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="部门介绍" prop="introduce">
          <el-input v-model="departForm.introduce" style="width:80%" placeholder="1-300个字符" type="textarea" />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submit">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import TreeTools from './components/tree-tools.vue'
import { getDepartmentList, getSimpleList, addDepartment, delDepartment, getDepartmentId, editDepartmentId } from '@/api'
import findSon from '@/utils/findSon'
export default {
  name: 'Dashboard',
  components: {
    TreeTools
  },
  data() {
    // 自定义校验项
  // 同级部门不能出现相同的部门名称
    const validateName = (rule, value, callback) => {
      let broArr = []
      if (this.departForm.id) {
        // 当前是编辑状态
        if (this.currentNode.name === value) {
          // 并且没有修改过部门名称
          callback()
          return
        }
        // 如果修改了部门名称
        broArr = this.originList.filter(item => item.pid === this.currentNode.pid)
      } else {
        broArr = this.originList.filter(item => this.currentNode.id === item.pid)
      }

      // 1.先找到添加子部门元素下的所有其他子部门
      // const broArr = this.originList.filter(item => this.currentNode.id === item.pid)
      // 2.当前数据的值value不能和 broArr 中任何一个元素中的name 字段一致
      const isName = broArr.some(item => item.name === value)
      if (isName) {
        callback(new Error(`同级部门下已经有${value}这个部门了`))
      } else {
        callback()
      }
    }
    // 部门编码不能出现相同的
    const validateCode = (rule, value, callback) => {
      if (this.departForm.id && this.currentNode.code === value) {
        callback()
        return
      }
      if (this.originList.some(item => item.code === value)) {
        // 如果返回的是true，说明有重复
        callback(new Error('部门编码不能一致'))
      } else {
        callback()
      }
    }
    return {
      loading: false,
      departForm: {
        name: '', // 部门名称
        code: '', // 部门编码
        manager: '', // 部门管理者
        introduce: '' // 部门介绍
      },
      departRules: {
        name: [
          { required: true, message: '部门名称不能为空', trigger: ['blur', 'change'] },
          { min: 1, max: 50, message: '部门名称要求1-50个字符', trigger: ['blur', 'change'] },
          { validator: validateName, trigger: 'blur' }
        ],
        code: [
          { required: true, message: '部门编码不能为空', trigger: ['blur', 'change'] },
          { min: 1, max: 50, message: '部门编码要求1-50个字符', trigger: ['blur', 'change'] },
          { validator: validateCode, trigger: 'change' }
        ],
        manager: [
          { required: true, message: '部门负责人不能为空', trigger: ['blur', 'change'] }
        ],
        introduce: [
          { required: true, message: '部门介绍不能为空', trigger: ['blur', 'change'] },
          { min: 1, max: 300, message: '部门介绍要求1-300个字符', trigger: ['blur', 'change'] }
        ]
      },
      dialogVisible: false, // 弹窗框的显示隐藏
      list: [], // 获取所有的企业
      employeeList: {}, // 获取员工简单列表的数据
      currentNode: {}, // 新增部门
      defaultProps: {
        label: 'name',
        children: 'children'
      },
      company: { name: '江苏传智播客教育科技股份有限公司', manager: '负责人', id: '' }
    }
  },
  computed: {
    title() {
      return this.departForm.id ? '编辑部门' : '新增部门'
    }
  },
  created() {
    this.fetchDepartment()
  },
  methods: {
    async fetchDepartment() {
      this.loading = true
      try {
        const res = await getDepartmentList()
        // console.log(res)
        // 封装了一个工具函数 找儿子的过程
        this.list = findSon(res.data.depts, '')
        // 原始数据
        this.originList = res.data.depts
        this.company.name = res.data.companyName
        this.loading = false
      } catch (error) {
        this.loading = false
      }
    },
    // 添加子部门
    add(val) {
      // 弹窗显示
      this.dialogVisible = true
      // 新增子部门的当前项
      this.currentNode = val
    },
    // 获取员工简单列表 打开弹窗回调
    async dialogOpen() {
      const { data } = await getSimpleList()
      // console.log(data)
      this.employeeList = data
    },
    // 关闭弹窗回调
    closeDialog() {
      this.dialogVisible = false
      // 在关闭弹窗的同时重置表单数据和校验结果
      this.$refs.departRef.resetFields()
      console.log(this.departForm)
      // 也可以加入手动重置
      this.departForm = {
        name: '', // 部门名称
        code: '', // 部门编码
        manager: '', // 部门管理者
        introduce: '' // 部门介绍
      }
    },
    // 提交事件
    submit() {
      // 1.兜底校验
      // 2.接口的声明
      // 3.接口的引入
      // 4.接口的调用
      // 5.收集整理参数
      // 6.关闭弹窗
      // 7.提示用户新增成功
      // 8.重现渲染页面
      // 9.表单的数据和校验的重置
      this.$refs.departRef.validate(async(valid) => {
        if (!valid) return false
        if (this.departForm.id) {
          // 编辑
          await editDepartmentId(this.departForm)
        } else {
          // 新增
          await addDepartment({
            ...this.departForm,
            pid: this.currentNode.id
          })
        }
        this.closeDialog()
        this.$message.success(this.title + '成功')
        this.fetchDepartment()
      })
    },
    // 删除功能
    // 1.准备删除部门的接口
    // 2.接口的引入
    // 3.绑定删除的点击事件
    // 4.提示用户是否删除的二次确认
    // 5.调用接口与 提示删除成功
    // 6.重新渲染页面
    del(val) {
      this.$confirm('确认删除?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async() => {
        await delDepartment(val.id)
        this.$message({
          type: 'success',
          message: '删除成功!'
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    // 编辑部门
    async edit(val) {
      // 编辑的过程
      // 1.编辑功能复用了新增的弹窗
      // 2.点击编辑按钮 触发绑定的点击事件 通知父组件
      // 3.父组件中接收子传父事件 显示新增弹窗
      // 4.在打开弹窗的时候需要调用获取详情数据的接口 对表单做赋值回显
      // 5.处理编辑逻辑和新增逻辑的不同 可以根据是否有id判断是否新增
      // 6.对校验逻辑 标题 提交之后的提示 提交接口进行修改
      // 7.定义接口 接口引入 接口调用
      // 8.关闭弹窗 提示用户 清空表单数据和校验 重新渲染页面

      // 存一下当前编辑的节点
      this.currentNode = val
      const { data } = await getDepartmentId(this.currentNode.id)
      this.departForm = data
      this.dialogVisible = true
    }
  }

}
</script>
<style lang="scss" scoped></style>
